commands: a command says whether it applies, and menus grey what does not - #121
Open
zmaril wants to merge 1 commit into
Open
commands: a command says whether it applies, and menus grey what does not#121zmaril wants to merge 1 commit into
zmaril wants to merge 1 commit into
Conversation
powderman previewhttps://powderman-pr-121.fly.dev The workbench, live: split/join/swap areas, the F3 palette, the widgets, themes, tooltips, the status bar. On branches with the MCP server, point an agent at it: claude mcp add --transport http powderman-preview "https://powderman-pr-121.fly.dev/mcp"Updated on every push. Destroyed when this PR closes. |
… not Blender's UI is operators, properties, poll and context. We had the first two and neither of the last two: every surface offered every command unconditionally, so "Close area" sat live in the menu of the only area and failed on the click, and the whole workspace family stayed live with one workspace. `Command` grows a `poll`. Most are `always` — there is no workbench where splitting an area makes no sense, which is exactly why it needs no poll of its own. The ones that do: join, join_into, ratio and swap want a second area; close, cycle, switch and move want a second workspace. `run` checks it too, not just the chrome. The chrome is not the only caller — an agent reaches the same registry — and a command that cannot apply should say so once, in one place, rather than failing differently depending on who asked. It refuses before touching anything, so a refused command is never a half-applied one. Menu rows grey rather than vanish. A row that disappears teaches nothing; a row that is there and dim says "this exists, not now". The shim excludes disabled rows from the list the arrows walk, which is the same list Enter fires and the letter accelerators match — leaving them in would have let the keyboard run what the pointer refuses. The library asks the host, through a new `can` callback, because the host holds the registry. A host that offers no answer gets every row live, which is what these menus did before there was a poll to ask. Not done here, and worth saying: the command palette is still a hardcoded list of five entries plus workspace switches — it never enumerated the registry at all. Enumerating it needs commands to declare their parameters, since most cannot run without an area id or a direction, and that is its own piece of work rather than a line in this one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjCx5QszLXroGYh1YBxybw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #120. First of the Blender-review sequence.
Blender's UI is four ideas: operators, properties,
poll(), and context. We had the first two and neither of the last two — every surface offered every command unconditionally. "Close area" sat live in the menu of the only area and failed on the click; the wholeworkspace.*family stayed live with one workspace.The field
Most are
always— there is no workbench where splitting an area makes no sense, which is exactly why it needs no poll of its own. The ones that aren't:many_areasmany_workspacesrunchecks it tooNot just the chrome. The chrome isn't the only caller — an agent reaches the same registry — and a command that can't apply should say so once, in one place, rather than failing differently depending on who asked. It refuses before touching anything, so a refused command is never a half-applied one.
Grey, not gone
A row that disappears teaches nothing; a row that's there and dim says this exists, not now.
MenuItem::when(available),disabledon the wire type (ts-rs regenerated), and the shim draws it dim and inert.The detail that matters: disabled rows are excluded from the list the arrows walk — the same list
Enterfires and the letter accelerators match. Leaving them in would have let the keyboard run what the pointer refuses.The library asks the host through a new
cancallback, because the host holds the registry. A host that offers no answer gets every row live, which is what these menus did before there was a poll to ask.What I did not do, deliberately
The command palette is still a hardcoded list of five entries plus workspace switches. It never enumerated the registry at all — that's not a design decision anyone made, it's a stub. But enumerating it needs commands to declare their parameters, since most can't run without an area id or a direction, and that's its own piece of work rather than a line in this one. Flagging it rather than half-doing it.
Four new tests, including that
runrefuses whatpollrefuses (a poll the chrome respects andrundoesn't is a poll an agent walks straight through) and thatavailableshrinks with the workbench.165 tests pass; fmt clean, clippy clean under
-D warnings, shims anddocs/reference.mdregenerated.🤖 Generated with Claude Code
https://claude.ai/code/session_01XjCx5QszLXroGYh1YBxybw